🔥 algorithm | February 09, 2021
리스트(List)는 말 그대로 순서대로 저장하는 시퀸스이자 변경 가능한 목록(Mutable List)이다.
특징은 다음과 같다.
입력 순서가 유지된다.
파이썬은 모든 것이 객체이며 리스트 또한 마찮가지이다.
내부적으로는 동적 배열로 구현되어 있다.
[리스트의 주요 연산 시간 복잡도]
연산 | 시간 복잡도 | 설명 |
---|---|---|
len(a) | O(1) | 전체 요소의 개수를 리턴한다. |
a[i] | O(1) | 인덱스 i의 요소를 가져온다. |
a[i:j] | O(k) | i부터 j까지 슬라이스의 길이만틈인 k개의 요소를 가져온다. 이경우 객체 k개에 대한 조회가 필요하므로 O(k)이다. |
elem in a | O(n) | elem 요소가 존재하는지 확인한다. 처음부터 순차 탐색하므로 n만큼 시간이 소요된다. |
a.count(elem) | O(n) | elem 요소의 개수를 리턴한다. |
a.indxe(elem) | O(n) | elem 요소의 인덱스를 리턴한다. |
a.append(elem) | O(1) | 리스트 마지막에 elem 요소를 추가한다. |
a.pop() | O(1) | 리스트 마지막 요소를 추출한다. 스택의 연산이다. |
a.pop(0) | O(n) | 리스트 첫번째 요소를 추출한다. 큐의 연산이다. 이 경우 전체 복사가 필요하므로 O(n)이다. |
del a[i] | O(n) | i에 따라 다르다. 최악의 경우 O(n)이다. |
a.sort() | O(n log n) | 정렬한다. 팀소트(Timsort)를 사용하며, 최선의 경우 O(n)에도 실행될 수 있다. |
min(a), max(a) | O(n) | 최솟값/최댓값을 계산하기 위해서는 전체를 선형 탐색해야 한다. |
a.reverse() | O(n) | 뒤집는다. |
리스트의 경우 탐색 시 값의 존재 유무를 확인하려면 정렬된 경우에는 이진 검색이 효율적이다.
존재하지 않는 인덱스를 조회할 경우 IndexError
가 발생한다.
인덱스로 삭제하기
del
키워드를 사용하면 인덱스로 삭제가 가능하다. ex) del a[1]값으로 삭제하기
remove()
함수를 사용하면 값에 해당하는 요소를 삭제할 수 있다. ex) a.remove(3)내부적으로는 해시 테이블(Hash Table)로 구현되어 있다. 해시할 수만 있다면 숫자 뿐만 아니라, 문자, 집합까지 불변 객체를 모두 키로 사용할 수 있다. 이 과정을 해싱이라고 하며, 해시 테이블을 이용해 자료를 저장한다. 또한 입력과 조회 모두 O(1)에 가능하다는 특징이 있다.
[딕셔너리의 주요 연산 시간 복잡도]
연산 | 시간 복잡도 | 설명 |
---|---|---|
len(a) | O(1) | 요소의 개수를 리턴한다. |
a[key] | O(1) | 키를 조회하여 값을 리턴한다. |
a[key] = value | O(1) | 키/값을 삽입한다. |
key in a | O(1) | 딕셔너리에 키가 존재하는지 확인한다. |
기존에 딕셔너리는 입력 순서가 유지되지 않았지만 파이썬 3.6 이하에서는 collections.OrderedDict()
라는 별도 자료형을 제공했었다. 그러나 3.7부터는 내부적으로 인덱스를 이용해 입력 순서를 유지한다.
또한 조회 시 항상 디폴트 값을 생성해 키 오류를 방지하는 collections.defaultdict()
,
요소의 값을 키로 하고 개수를 값 형태로 만들어 카운팅 하는 collections.Counter()
등이 있다.
딕셔너리에서는 존재하지 않는 키를 조회하면 KeyError
에러가 발생한다.
에러처리 방법
del a['key4']
try:
print(a['key4'])
except KeyError:
print('존재하지 않는 키')
'key4' in a
>> Fasle
if 'key4' in a:
print('존재하는 키')
else:
print('존재하지 않는 키')
또한 키/값을 for 반복문으로도 조회가 가능하다.
for k, v in a.items():
print(k, v)
a = collections.defaultdict(int)
a['A'] = 5
a['B'] = 4
>>> a
defaultdict(<class 'int'>, {'A': 5, 'B': 4})
# C라는 키는 존재하지 않는다.
a['C'] += 1
>>> a
defaultdict(<class 'int'>, {'A': 5, 'B': 4,'C': 1})
원래라면 C 키 값에 +1
를 해주면 KeyError가 발생했겠지만 에러 없이 자동으로 디폴트인 0을 기준으로 자동 생성한 후 여기에 1을 더해줬다.
>>> a = [1, 2, 3, 4, 5, 5, 5, 6, 6]
>>> b = collections.Counter(a)
>>> b
Counter({5: 3, 6:2, 1:1, 2: 1, 3: 1, 4: 1})
가장 빈도 수가 높은 요소는 most_common()
을 사용하면 된다.
b.most_common(2) = [(5, 3), (6, 2)]